<?php
#
# dmBridge: a data access framework for CONTENTdm(R)
#
# Copyright © 2009, 2010, 2011 Board of Regents of the Nevada System of Higher
# Education, on behalf of the University of Nevada, Las Vegas
#

/**
 * Represents an individual rating that a user has given to an object.
 * Conceptually/semantically, a rating can also mean some sort of overall
 * calculation on all of the object's combined ratings (such as mean, median,
 * etc.); for this, use DMObject::getRating().
 *
 * @author Alex Dolski <alex.dolski@unlv.edu>
 * @license http://www.opensource.org/licenses/mit-license.php
 */
class DMRating extends DMAbstractSocialEntity implements DMSocialEntity {

	private $max;


	/**
	* A rating value has no meaning without a scale: 1 out of 5, 8 out of 10,
	* etc. This constructor takes a value and the max value of the scale.
	* Ratings are transparently normalized to a scale of 0-100 for storage.
	*
	* @param int value
	* @param int max
	* @throws DMIllegalArgumentException
	*/
	public function __construct($value, $max) {
		parent::__construct();
		$this->setApproved(true);
		if ($value > $max) {
			throw new DMIllegalArgumentException(
				DMLocalizedString::getString('RATING_LARGER_THAN_MAX'));
		}
		$this->setValue($value);
		$this->setMax($max);
	}

	/**
	 * Returns the rating's value as a string, rounded to 2 decimal places. Do
	 * not depend on this method, as it is not guaranteed to be stable;
	 * DMRating::getValue() is more precise and preferred.
	 *
	 * @return string
	 * @see DMRating::getValue()
	 */
	public function __toString() {
		return (string) round($this->getValue(), 2);
	}

	/**
	* @return float The largest value of the rating scale
	*/
	public final function getMax() {
		return $this->max;
	}

	/**
	* @param float max A positive number
	* @throws DMIllegalArgumentException
	*/
	public final function setMax($max) {
		if ((!is_numeric($max) or $max <= 0)
				or (!is_null($this->getValue()) && $max < $this->getValue())) {
			throw new DMIllegalArgumentException(
				DMLocalizedString::getString('INVALID_MAX_RATING'));
		}
		$this->max = (float) $max;
	}

	/**
	 * Normalizes the rating to a scale of 0-100 for storage.
	 *
	 * @return float
	 */
	public final function getNormalizedValue() {
		return (float) $this->getValue() * (100 / $this->getMax());
	}

	/**
	 * Exists to comply with DMSocialEntity. Currently doesn't do anything.
	 *
	 * @return null
	 */
	public function getURI() {
		return null;
	}

	/**
	* @param float float
	* @throws DMIllegalArgumentException
	*/
	public function setValue($float) {
		if (!is_numeric($float) || $float < 0) {
			throw new DMIllegalArgumentException(
				DMLocalizedString::getString('INVALID_RATING'));
		}
		$this->value = (float) $float;
	}

}
